package com.citycloud.ccuap.tc.common.result;

import java.io.Serializable;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(value = "后端接口统一返回对象")
public class ResultObject<T> implements Serializable {
	private static final long serialVersionUID = 1L;

	@ApiModelProperty(value = "返回码code", required = true)
	private String code;

	@ApiModelProperty(value = "返回提示信息", required = false)
	private String message;

	@ApiModelProperty(value = "返回信息主体", required = false)
	private T data;

	/** 让构造函数为 private，这样该类就不会被实例化 */
	private ResultObject() {
	}

	/** 获取唯一对象 */
	public static  ResultObject getInstance() {
		return Lazy.INSTANCE;
	}

	/** 使用静态内部类实现线程安全，提高性能 */
	private static class Lazy {
		private static final ResultObject INSTANCE = new ResultObject();
	}

	/**
	 * Instantiates a new result.
	 *
	 * @param code    the code
	 * @param message the message
	 * @param data    the data
	 */
	private ResultObject(String code, String message, T data) {
		this.code = code;
		this.message = message;
		this.data = data;
	}

	private ResultObject<T> get(String code, String msg, T data) {
		return new ResultObject<T>(code, msg, data);
	}

	/**
	 * return success 200 message=""和data=null.
	 *
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> success() {
		return successMsg("");
	}

	/**
	 * return success 204 只有message.
	 *
	 * @param msg msg
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> successMsg(String msg) {
		return success(msg, null);
	}

	/**
	 * return success 200 默认message，前端只关注data.
	 *
	 * @param data this is result data.
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> success(T data) {
		return success(ResultCodeEnum.SUCCESSFUL.getCode(), data);
	}

	/**
	 * return success 200 message和data都定义.
	 *
	 * @param msg  this ext msg.
	 * @param data this is result data.
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> success(String msg, T data) {
		return get(ResultCodeEnum.SUCCESSFUL.getCode(), msg, data);
	}

	/**
	 * return error .
	 *
	 * @param msg error msg
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> error(String msg) {
		return error(ResultCodeEnum.ERROR.getCode(), msg);
	}

	/**
	 * return error .
	 *
	 * @param code error code
	 * @param msg  error msg
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> error(String code, String msg) {
		return get(code, msg, null);
	}

	/**
	 * @param resultCodeEnum
	 * @return
	 */
	public ResultObject<T> error(ResultCodeEnum resultCodeEnum) {
		return get(resultCodeEnum.getCode(), resultCodeEnum.getMessage(), null);
	}

	/**
	 * @param resultCodeEnum
	 * @param message
	 * @return
	 */
	public ResultObject<T> error(ResultCodeEnum resultCodeEnum, String message) {
		return get(resultCodeEnum.getCode(),
				message != null && !message.isEmpty() ? message : resultCodeEnum.getMessage(), null);
	}

	public ResultObject<T> error(Exception e) {
		if (e.getMessage() == null) {
			return get(ResultCodeEnum.ERROR.getCode(), e.getCause().getMessage(), null);
		} else {
			return get(ResultCodeEnum.ERROR.getCode(), e.getMessage(), null);
		}

	}

	/**
	 * return timeout .
	 *
	 * @param msg error msg
	 * @return {@linkplain ResultObject}
	 */
	public ResultObject<T> timeout(String msg) {
		return error(ResultCodeEnum.REQUEST_TIMEOUT.getCode(), msg);
	}

}
